package com.hinner.config.security;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hinner.common.Result;
import com.hinner.entity.SysMenu;
import com.hinner.entity.SysRole;
import com.hinner.entity.SysUser;
import com.hinner.service.SysMenuService;
import com.hinner.service.SysRoleService;
import com.hinner.service.SysUserService;
import com.hinner.util.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * spring security 登录成功处理器
 */
@Component  //可以被自动导入
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private SysRoleService sysRoleService;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        // 登录成功后的处理
        httpServletResponse.setContentType("application/json;charset=utf-8");
        ServletOutputStream out = httpServletResponse.getOutputStream();

        HashMap<String, Object> resultMap = new HashMap<>();
        // 内容
        String username = authentication.getName(); //不能写死
        String token = JwtUtils.genJwtToken(username);

        /*
            返回菜单树
            1. 根据用户名拿到用户信息
            2. 从而得到角色信息，菜单信息

         */
        SysUser currentUser = sysUserService.getUserByUserName(username);
        // 不需要对用户进行判空，因为在登录的时候已经判断过了，如果为空，就会抛出异常（走LoginFailureHandler）

        // 拿到角色关联的菜单信息
        Set<SysMenu> set = new HashSet<>();
        List<SysRole> roleList = sysRoleService.list(new QueryWrapper<SysRole>().inSql("id", "select role_id from sys_user_role where user_id = " + currentUser.getId()));
        if (CollectionUtil.isNotEmpty(roleList)){
            // 用户信息中加一个角色信息，逗号隔开
            currentUser.setRoles(roleList.stream().map(role -> role.getName()).collect(Collectors.joining(",")));

            for (SysRole role : roleList) {
                List<SysMenu> menuList = sysMenuService.list(new QueryWrapper<SysMenu>().inSql("id", "select menu_id from sys_role_menu where role_id = " + role.getId()));
                // 去重
                if (CollectionUtil.isNotEmpty(menuList)){
                    set.addAll(menuList);
                }
            }
        }
        List<SysMenu> list = new ArrayList<>(set);
        list.sort(Comparator.comparingInt(SysMenu::getOrderNum));

        // 构建菜单树
        List<SysMenu> menuList  = sysMenuService.buildMenuTree(list);


        // 多返回点内容
        resultMap.put("token",token);
        resultMap.put("currentUser",currentUser);
        resultMap.put("menuList",menuList);
        byte[] bytes = JSONUtil.toJsonStr(Result.success(resultMap)).getBytes();

        //
        out.write(bytes);
        out.flush();
        out.close();
    }
}
